package com.may._4;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

class  myCache{//资源类
    private volatile Map<String,Object> map = new HashMap<>();//所有缓存资源必须用 volatile 修饰

    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    public void put(String key,Object value){
        rwLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"\t 正在写入:"+key);
            try {TimeUnit.SECONDS.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}//模拟网络拥堵
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"\t 写入完成");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            rwLock.writeLock().unlock();
        }
    }

    public void get(String key){
        rwLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"\t 正在读取");
            try {
                TimeUnit.MILLISECONDS.sleep(300);//模拟网络拥堵
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Object result = map.get(key);
            System.out.println(Thread.currentThread().getName()+"\t 读取完成:"+result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwLock.readLock().unlock();
        }
    }
    /**暂时不用这个
    public void clearMap(){
        map.clear();//清除缓存
    }
     */
}
/**
 * 如果有一个线程在写共享资源，就不应该有其他线程对该资源进行读或写。
 * 读-读能共存
 * 读-写不能共存
 * 写-写不能共存
 *
 * 写操作：原子+独占，整个过程必须完整，不可被打断。
 */
public class ReadWriteLockDemo {
    public static void main(String[] args) {
        myCache myCache = new myCache();
        for (int i = 0; i < 5; i++){
            final String s = String.valueOf(i);
            new Thread(() -> {
               myCache.put(s,s);
            },String.valueOf(i)).start();
        }

        for (int i = 0; i < 5; i++){
            final String s = String.valueOf(i);
            new Thread(() -> {
                myCache.get(s);
            },String.valueOf(i)).start();
        }
    }
}
